/**
 * TodoList
 *
 */

import React, { FunctionComponent } from 'react';
import { connect } from 'react-redux';
import { Dispatch, bindActionCreators } from 'redux';
import { createSelector } from 'reselect';
import { TransitionMotion, spring } from 'react-motion';
import { List } from 'antd';
import { AppState } from '../../Stores';

import { EditorForm } from '../../Stores/Todo/EditorForm/types';
import { TodoItem as TodoItemType } from '../../Stores/Todo/TodoList/types';
import { TodoListFooter, FilterTypes } from '../../Stores/Todo/TodoListFooter/types';

import { toggleTodo, removeTodo, updateTodo } from '../../Stores/Todo/TodoList/action';
import { changeEditorVal, changeTargetId } from '../../Stores/Todo/EditorForm/action';
import { setFilterType, clearCompletedItems } from '../../Stores/Todo/TodoListFooter/action';

import TodoItem from './TodoItem';
import ListFooter from './TodoListFooter';
import styles from './index.scss';

export interface TodoListProps {
  list: TodoItemType[];
  editorForm: EditorForm;
  listFooter: TodoListFooter;
  onToggleTodo: (id: string, isCompleted?: boolean) => void;
  onRemoveTodo: (id: string) => void;
  onChangeEditorVal: (value: string) => void;
  onChangeTargetId: (id: string) => void;
  onUpdateTodo: (id: string, title: string) => void;
  onSetFilterType: (filterType: FilterTypes) => void;
  onClearCompletedItems: () => void;
}

const TodoList: FunctionComponent<TodoListProps> = ({ list, editorForm, listFooter, ...props }) => {
  const willEnter = () => ({ opacity: 0 });

  return (
    <div className={styles.todoList}>
      <TransitionMotion willEnter={willEnter} styles={list.map(item => ({ key: item.id, style: { opacity: spring(1) }, data: item }))}>
        {interpolatedStyles => (
          <List
            size="small"
            bordered={true}
            footer={
              <ListFooter
                listLength={list.length}
                filterType={listFooter.filterType}
                onSetFilterType={props.onSetFilterType}
                onClearCompletedItems={props.onClearCompletedItems}
              />
            }
          >
            {interpolatedStyles.map(item => (
              <TodoItem
                key={item.key}
                style={{ opacity: item.style.opacity }}
                todoItem={item.data}
                editorForm={editorForm}
                onToggleTodo={props.onToggleTodo}
                onRemoveTodo={props.onRemoveTodo}
                onChangeEditorVal={props.onChangeEditorVal}
                onChangeTargetId={props.onChangeTargetId}
                onUpdateTodo={props.onUpdateTodo}
              />
            ))}
          </List>
        )}
      </TransitionMotion>
    </div>
  );
};

const getFilterType = (state: AppState) => state.todo.listFooter.filterType;
const getTodoList = (state: AppState) => state.todo.list;
const filterTodoList = createSelector(
  [getFilterType, getTodoList],
  (filterType, list) => {
    switch (filterType) {
      case FilterTypes.All:
        return list;
      case FilterTypes.Active:
        return list.filter(item => !item.isCompleted);
      case FilterTypes.Completed:
        return list.filter(item => item.isCompleted);
      default:
        return list;
    }
  }
);

const mapStateToProps = (state: AppState) => ({
  editorForm: state.todo.editorForm,
  list: filterTodoList(state),
  listFooter: state.todo.listFooter
});

const mapDispatchToProps = (dispatch: Dispatch) =>
  bindActionCreators(
    {
      onToggleTodo: toggleTodo,
      onRemoveTodo: removeTodo,
      onChangeEditorVal: changeEditorVal,
      onChangeTargetId: changeTargetId,
      onUpdateTodo: updateTodo,
      onSetFilterType: setFilterType,
      onClearCompletedItems: clearCompletedItems
    },
    dispatch
  );

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);
